package com.cloudcc.boot.controller;

import com.yangzg.cloudcc.openapi.configure.CloudccOpenApiConfig;
import com.yangzg.cloudcc.openapi.entity.CloudccOpenApiAccessUser;
import com.yangzg.cloudcc.openapi.service.CloudccOpenApiService;
import com.yangzg.cloudcc.openapi.service.CloudccOpenApiTokenService;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@Slf4j
public class LoginController {

    //    private static String paramFilter = "database \\(|database\\(|length \\(|length\\(|'|#include |#function |#echo |#foreach\\(|#foreach \\(|#else |#if\\(|#if \\(|#list\\(|#list \\(|#set\\(|#set \\(|'or |'or'|'or/\\*|' or |' or'|'and |'and/\\*|' and |'and'|' and'|'union |'union'|'union/\\*|' union |' union'|' union/\\*|'/\\*|' /\\*|javascript:|javascript :|alert\\(|alert \\(|console.log\\(|<script|<iframe|<frame|<confirm|eval\\(|eval \\(|onerror=|onerror =|onmouseleave=|onmouseleave =|onclick=|onclick =|ondatabinding=|ondatabinding =|ondblclick=|ondblclick =" +
//            "|ondisposed=|ondisposed =|oninit=|oninit =|onkeydown=|onkeydown =|onkeypress=|onkeypress =|onkeyup=|onkeyup =|onload=|onload =|onmousedown=|onmousedown =|onmousemove=|onmousemove =|onmouseout=|onmouseout =|onmouseover=|onmouseover =|onmouseup=|onmouseup =|onprerender=|onprerender =|onunload=|onunload =|onfocus=|onfocus =|union /\\*|union/\\*|updatexml\\(|updatexml \\(";
    private static final String paramFilter = "database \\(|database\\(|length \\(|length\\(|#include |#function |#echo |#foreach\\(|#foreach \\(|#else |#if\\(|#if \\(|#list\\(|#list \\(|#set\\(|#set \\(|'or |'or'|'or/\\*|' or |' or'|'and |'and/\\*|' and |'and'|' and'|'union |'union'|'union/\\*|' union |' union'|' union/\\*|'/\\*|' /\\*|javascript:|javascript :|alert\\(|alert \\(|console.log\\(|<script|<iframe|<frame|<confirm|eval\\(|eval \\(|onerror=|onerror =|onmouseleave=|onmouseleave =|onclick=|onclick =|ondatabinding=|ondatabinding =|ondblclick=|ondblclick =" +
            "|ondisposed=|ondisposed =|oninit=|oninit =|onkeydown=|onkeydown =|onkeypress=|onkeypress =|onkeyup=|onkeyup =|onload=|onload =|onmousedown=|onmousedown =|onmousemove=|onmousemove =|onmouseout=|onmouseout =|onmouseover=|onmouseover =|onmouseup=|onmouseup =|onprerender=|onprerender =|onunload=|onunload =|onfocus=|onfocus =|union /\\*|union/\\*|updatexml\\(|updatexml \\(|extractvalue\\(|extractvalue \\(|substring\\(|substring \\(|string-length \\(|string-length\\(|extractvalue|'|ST_LongFromGeoHash| select|select |= | =|0x7e";

    public LoginController(CloudccOpenApiConfig cloudccOpenApiConfig, CloudccOpenApiService cloudccOpenApiService, CloudccOpenApiTokenService cloudccOpenApiTokenService) {
        this.cloudccOpenApiConfig = cloudccOpenApiConfig;
        this.cloudccOpenApiService = cloudccOpenApiService;
        this.cloudccOpenApiTokenService = cloudccOpenApiTokenService;
    }

    private final CloudccOpenApiConfig cloudccOpenApiConfig;

    private final CloudccOpenApiService cloudccOpenApiService;

    private final CloudccOpenApiTokenService cloudccOpenApiTokenService;

    @PostMapping("/login")
    public Map<String, String> login(@RequestParam String login_name, @RequestParam String login_pwd) {
        Map<String, String> data = new HashMap<>();
        if ("".equals(login_name) || "".equals(login_pwd)) {
            data.put("result", "false");
            data.put("msg", "请维护用户名、密码");
        } else {
            boolean validate = isInjection(login_name);
            if (validate) {
                data.put("result", "false");
                data.put("msg", "非法参数！");
                log.warn("login_name - {} 登录失败:包含非法参数", login_name);
            } else {
                String sql = "select * from tp_sys_user where login_name = '%s' and pwd = '%s'".formatted(login_name, login_pwd);
                List<JSONObject> userList = cloudccOpenApiService.cqlQueryDataListWithLogInfo(sql, JSONObject.class);
                if (CollectionUtils.isEmpty(userList)) {
                    data.put("result", "false");
                    data.put("msg", "用户名或密码错误");
                    log.warn("login_name - {} 登录失败:用户名或密码错误", login_name);
                } else {
                    JSONObject dataJson = userList.getFirst();
                    String isUsing = Objects.toString(dataJson.getString("ISUSING"), "1");
                    if ("0".equals(isUsing)) {
                        data.put("result", "false");
                        data.put("msg", "用户未启用，请联系管理员");
                        log.warn("login_name - {} 登录失败:用户未启用", login_name);
                    } else {
                        String isFirstLogin = Objects.toString(dataJson.getString("ISFIRSTLOGIN"), "false");
                        String safety_mark = Objects.toString(dataJson.getString("SAFETY_MARK"), "");
                        String userId = Objects.toString(dataJson.getString("ID"), "");
                        CloudccOpenApiAccessUser cloudccOpenApiAccessUser = CloudccOpenApiAccessUser.builder()
                                .userId(userId)
                                .loginName(login_name)
                                .safetyMark(safety_mark)
                                .using(Integer.parseInt(isUsing))
                                .build();
                        String userAccessToken = cloudccOpenApiTokenService.getToken(cloudccOpenApiAccessUser);
                        data.put("result", "true");
                        String loginUrl = cloudccOpenApiConfig.getSso().getMainAppGatewayUri() + "/#/";
                        if ("true".equals(isFirstLogin)) {
                            data.put("msg", MessageFormat.format("{0}changePassword?username={1}&modifyPwType=changePassword&accessToken={2}", loginUrl, login_name, userAccessToken));//返回首次登陆修改密码页面
                            log.debug("login_name - {} 登录成功:首次登陆", login_name);
                        } else {
                            data.put("msg", "%s%s?binding=%s".formatted(loginUrl, "homePageObject/standardPage", userAccessToken));//返回正常登陆链接
                            log.debug("login_name - {} 登录成功", login_name);
                        }
                    }
                }
            }
        }
        return data;
    }


    public static boolean isInjection(String content) {
        if (StringUtils.isBlank(content)) {
            return false;
        } else {
            boolean urlEncoded = isUrlEncoded(content);
            if (urlEncoded) {
                content = content.replaceAll("\\+", "%2B");
                try {
                    content = URLDecoder.decode(content, StandardCharsets.UTF_8);
                } catch (Exception e) {
                    log.error("isInjection error:{}", e.getMessage(), e);
                }
            }
            boolean html = isHtml(content);
            if (html) {
                content = StringEscapeUtils.unescapeHtml(content);
            }
            content = content.replaceAll("\\s+", " ");
        }
        int length = content.length();
        content = content.toLowerCase();
        String newContent = replaceSql(content);
        return length != newContent.length();
    }


    public static boolean isUrlEncoded(String input) {
        if (input == null || input.isEmpty()) {
            return false;
        }

        // 匹配URL编码格式
        String urlEncodedPattern = "%[0-9A-Fa-f]{2}";
        Pattern urlEncodedPatternRegex = Pattern.compile(urlEncodedPattern);
        Matcher urlEncodedMatcher = urlEncodedPatternRegex.matcher(input);

        // 检查是否包含URL编码格式
        return urlEncodedMatcher.find();
    }

    public static boolean isHtml(String input) {
        if (input == null || input.isEmpty()) {
            return false;
        }

        // 匹配HTML标签
        String tagPattern = "<[^>]*>";
        Pattern tagPatternRegex = Pattern.compile(tagPattern);
        Matcher tagMatcher = tagPatternRegex.matcher(input);
        boolean containsTag = tagMatcher.find();

        // 匹配HTML实体
        String entityPattern = "&[a-zA-Z0-9#]+;";
        Pattern entityPatternRegex = Pattern.compile(entityPattern);
        Matcher entityMatcher = entityPatternRegex.matcher(input);
        boolean containsEntity = entityMatcher.find();

        return containsTag || containsEntity;
    }


    private static String getSqlResult(String searchKeyword) {
        if (StringUtils.isNotBlank(searchKeyword)) {
            searchKeyword = searchKeyword.replaceAll("(?i:" + paramFilter + ")", "");
        }
        return searchKeyword;
    }

    private static String replaceSql(String searchKeyword) {
        if (Objects.nonNull(searchKeyword)) {
            while (searchKeyword.getBytes().length > getSqlResult(searchKeyword).getBytes().length) {
                searchKeyword = getSqlResult(searchKeyword);
            }
        }
        return searchKeyword;
    }

}
